﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;

namespace WindowsTest
{
    /// <summary>
    /// 图像效果类
    /// </summary>
    public class ImageEffects
    {
        /// <summary>
        /// 雾化效果 
        /// </summary>
        /// <param name="bm">输入的图像</param>
        /// <returns>雾化效果图像</returns>
        public static Bitmap FogEffect(Bitmap bm)
        {
            var w = bm.Width;
            var h = bm.Height;
            var obm = new Bitmap(w, h);
            var data = bm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            var dataObm = obm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

            unsafe
            {
                var ptr = (byte*)data.Scan0.ToPointer();
                var ptr2 = (byte*)dataObm.Scan0.ToPointer();
                for (int i = 0; i < w; i++)
                {
                    for (int j = 0; j < h; j++)
                    {
                        var random = new Random();
                        int k = random.Next(123456);

                        var dx = i + k % 19;
                        var dy = j + k % 19;
                        dx = dx > w - 1 ? w - 1 : dx;
                        dy = dy > h - 1 ? h - 1 : dy;

                        //var pixel = bm.GetPixel(dx, dy);
                        //obm.SetPixel(i,j,pixel);

                        var _ptr = ptr + dy * data.Stride + dx * 3;
                        var _ptr2 = ptr2 + j * dataObm.Stride + i * 3;
                        _ptr2[0] = _ptr[0];
                        _ptr2[1] = _ptr[1];
                        _ptr2[2] = _ptr[2];
                    }
                }
            }

            bm.UnlockBits(data);
            obm.UnlockBits(dataObm);
            return obm;
        }

        /// <summary>
        /// 浮雕效果
        /// </summary>
        /// <param name="bm">输入的图像</param>
        /// <returns>浮雕效果图像</returns>
        public static Bitmap EmbossEffect(Bitmap bm)
        {
            var w = bm.Width;
            var h = bm.Height;
            var data = bm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                var ptr = (byte*)data.Scan0.ToPointer();
                for (int j = 0; j < h; j++)
                {
                    for (int i = 0; i < w - 1; i++)
                    {
                        var _ptr = ptr + j * data.Stride + i * 3;
                        var _ptrN = ptr + j * data.Stride + (i + 1) * 3;

                        //浮雕效果：对图像像素点的像素值分别与相邻像素点的像素值相减后加上128，然后将其作为新的像素点的值。
                        var r = _ptr[2] - _ptrN[2] + 128;
                        var g = _ptr[1] - _ptrN[1] + 128;
                        var b = _ptr[0] - _ptrN[0] + 128;

                        //处理颜色值溢出
                        r = (r < 0) ? 0 : ((r > 255) ? 255 : r);
                        g = (g < 0) ? 0 : ((g > 255) ? 255 : g);
                        b = (b < 0) ? 0 : ((b > 255) ? 255 : b);

                        _ptr[2] = (byte)r;
                        _ptr[1] = (byte)g;
                        _ptr[0] = (byte)b;
                    }
                }
            }

            bm.UnlockBits(data);

            return bm;
        }

        /// <summary>
        /// 镶嵌效果
        /// </summary>
        /// <param name="bm">输入的图像</param>
        /// <returns>镶嵌效果图像</returns>
        public static Bitmap InlayEffect(Bitmap bm)
        {
            var w = bm.Width;
            var h = bm.Height;
            var data = bm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                var ptr = (byte*)data.Scan0.ToPointer();
                for (int j = 1; j < h - 3; j++)
                {
                    for (int i = 1; i < w - 3; i++)
                    {
                        int r = 0, g = 0, b = 0;
                        for (int k = -1; k <= 1; k++)
                        {
                            for (int l = -1; l <= 1; l++)
                            {
                                var p = ptr + (j + k) * data.Stride + (i + l) * 3;
                                r += p[2];
                                g += p[1];
                                b += p[0];
                            }
                        }

                        var aveR = r / 9;
                        var aveG = g / 9;
                        var aveB = b / 9;

                        for (int k = -1; k <= 1; k++)
                        {
                            for (int l = -1; l <= 1; l++)
                            {
                                var _p = ptr + (j + k) * data.Stride + (i + l) * 3;
                                _p[2] = (byte)aveR;
                                _p[1] = (byte)aveG;
                                _p[0] = (byte)aveB;
                            }
                        }
                    }
                }
            }

            bm.UnlockBits(data);
            return bm;
        }

        /// <summary>
        /// 平滑效果
        /// </summary>
        /// <param name="bm">输入的图像</param>
        /// <returns>平滑效果图像</returns>
        public static Bitmap SmoothEffect(Bitmap bm)
        {
            var w = bm.Width;
            var h = bm.Height;
            var data = bm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                var ptr = (byte*)data.Scan0.ToPointer();
                for (int j = 1; j < h - 1; j++)
                {
                    for (int i = 1; i < w - 1; i++)
                    {
                        int r = 0, g = 0, b = 0;
                        for (int k = -1; k <= 1; k++)
                        {
                            for (int l = -1; l <= 1; l++)
                            {
                                var p = ptr + (j + k) * data.Stride + (i + l) * 3;
                                r += p[2];
                                g += p[1];
                                b += p[0];
                            }
                        }

                        var aveR = r / 9;
                        var aveG = g / 9;
                        var aveB = b / 9;

                        var _p = ptr + j * data.Stride + i * 3;
                        _p[2] = (byte)aveR;
                        _p[1] = (byte)aveG;
                        _p[0] = (byte)aveB;
                    }
                }
            }

            bm.UnlockBits(data);
            return bm;
        }

        /// <summary>
        /// 柔化效果
        /// </summary>
        /// <param name="bm">输入的图像</param>
        /// <returns>柔化效果图像</returns>
        public static Bitmap SoftEffect(Bitmap bm)
        {
            var w = bm.Width;
            var h = bm.Height;
            var data = bm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                var ptr = (byte*)data.Scan0.ToPointer();
                int[] Gauss = { 1, 2, 1, 2, 4, 2, 1, 2, 1 };//高斯模板

                for (int j = 1; j < h - 1; j++)
                {
                    for (int i = 1; i < w - 1; i++)
                    {
                        var index = 0;
                        int r = 0, g = 0, b = 0;
                        for (int k = -1; k <= 1; k++)
                        {
                            for (int l = -1; l <= 1; l++)
                            {
                                var p = ptr + (j + k) * data.Stride + (i + l) * 3;
                                r += p[2] * Gauss[index];
                                g += p[1] * Gauss[index];
                                b += p[0] * Gauss[index];
                                index++;
                            }
                        }

                        //柔化程度可以通过系数去控制，这里的16就是柔化系数
                        r = r / 16;
                        g = g / 16;
                        b = b / 16;

                        //处理颜色值溢出
                        r = (r < 0) ? 0 : ((r > 255) ? 255 : r);
                        g = (g < 0) ? 0 : ((g > 255) ? 255 : g);
                        b = (b < 0) ? 0 : ((b > 255) ? 255 : b);

                        var _ptr = ptr + j * data.Stride + i * 3;
                        _ptr[2] = (byte)r;
                        _ptr[1] = (byte)g;
                        _ptr[0] = (byte)b;
                    }
                }
            }

            bm.UnlockBits(data);
            return bm;
        }

        /// <summary>
        /// 霓虹效果
        /// </summary>
        /// <param name="bm">输入的图像</param>
        /// <returns>霓虹效果图像</returns>
        public static Bitmap NeonEffect(Bitmap bm)
        {
            var w = bm.Width;
            var h = bm.Height;
            var data = bm.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                var ptr = (byte*)data.Scan0.ToPointer();
                for (int j = 0; j < h - 1; j++)
                {
                    for (int i = 0; i < w - 1; i++)
                    {
                        var p1 = ptr + j * data.Stride + i * 3;
                        var p2 = ptr + j * data.Stride + (i + 1) * 3;
                        var p3 = ptr + (j + 1) * data.Stride + i * 3;
                        //对于3*3点阵，首先计算原图象像素f(i,j)的红，绿，蓝分量与相同行f（i+1，j）及同列f(i,j+1)相邻象素的梯度，即差的平方之和的平方根，然后将梯度值作为处理后的象素g(i,j)的红，绿，蓝分量值。
                        var r = Math.Sqrt(2 * ((p1[2] - p2[2]) * (p1[2] - p2[2]) + (p1[2] - p3[3]) * (p1[2] - p3[2])));
                        var g = Math.Sqrt(2 * ((p1[1] - p2[1]) * (p1[1] - p2[1]) + (p1[1] - p3[1]) * (p1[1] - p3[1])));
                        var b = Math.Sqrt(2 * ((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[0] - p3[0]) * (p1[0] - p3[0])));

                        p1[2] = (byte)r;
                        p1[1] = (byte)g;
                        p1[0] = (byte)b;
                    }
                }
            }

            bm.UnlockBits(data);
            return bm;
        }
    }
}
